﻿#include <QEventLoop>
#include "MainWindow.h"
#include "qtimer.h"
#include "qpushbutton.h"
#include "./ui_MainWindow.h"
#include "auto_trigger/utils/utils.h"
#include "libdaq/device/base_device.h"
#include "auto_trigger/connect_page/connect_page.h"
#include "auto_trigger/continuous_read_thread/continuous_read_thread.h"

using namespace libdaq::device;
QThreadPool read_data_thread_pool_;  // 线程池
std::vector<std::shared_ptr<std::vector<float>>> ADC_Data_Buffer(2); // 连续采集数据缓存
std::vector<bool> ADCDataState = {false, false};

MainWindow::MainWindow(QWidget *parent)
  : QMainWindow(parent), ui(new Ui::MainWindow) {
  ui->setupUi(this);
  qRegisterMetaType<std::vector<std::vector<float> > >("std::vector<std::vector<float>>");
  // 创建设备
  base_device_ = NewDevice();
  connect(ui->Connnectbutton, &QPushButton::clicked, this, &MainWindow::ClickConnectAction);
  connect(ui->StartADCCollection, &QPushButton::clicked, this, &MainWindow::ClickStartADCCollectionAction);
  connect(ui->UpdateConfig, &QPushButton::clicked, this, &MainWindow::ClickUpdateConfig);
  connect(ui->OnceCollection, &QPushButton::clicked, this, &MainWindow::ClickSoftwareTrigger);
  connect(ui->StopADCCollection, &QPushButton::clicked, this, &MainWindow::ClickStopADCCollection);

  InitWaveWidget();

}

MainWindow::~MainWindow() {
  delete ui;
}

void MainWindow::ConnectStatusSlot(bool status, ConnectPage::ConnectType type) {
  if (status) {
    if (!base_device_->InitializeDevice()) {
      qWarning(u8"初始化设备失败，请检查配置参数是否存在错误");
      return;
    }
    if (!base_device_->ConnectedDevice()) {
      qWarning(u8"发送连接设备命令失败");
      return;
    }
  }
}

void MainWindow::ClickConnectAction() {
  ConnectPage connect_page(base_device_, nullptr);
  // 初始化连接界面
  if (connect_page_.isNull()) {
    connect_page_.reset(new ConnectPage(base_device_));
    connect_page_->setModal(false);
    connect(connect_page_.get(), &ConnectPage::ConnectStatus, this, &MainWindow::ConnectStatusSlot);
  }
  connect_page_->InitParams(base_device_);
  connect_page_->show();
}

void MainWindow::ClickStartADCCollectionAction() {
  is_start_adc_collection_ = true;
  AutomaticCollection();
  qInfo(u8"启动ADC采集成功");
}

void MainWindow::ClickUpdateConfig() {
  // 采样率 1M
  auto legal_sample_rate = base_device_->GetADCLegalSampleRate();
  if (!base_device_->ConfigADCSampleRate(LockzhinerADCSampleRate::ADCSampleRate_1_M)) {
    qWarning(u8"采样率配置失败");
  }
  // 电压量程 1V
  if (!base_device_->ConfigADCVoltage(LockzhinerADCVoltage::ADCVoltage_1_V)) {
    qWarning(u8"电压量程配置失败");
  }
  // 2通道使能
  if (!base_device_->ConfigADCChannel(0x03)) {
    qWarning(u8"ADC2通道配置失败");
  }
  // 触发电平 0mv
  uint32_t level = 0;
  // 双边缘触发 自动触发 软件触发
  auto type = static_cast<LockzhinerADCTriggerType>(LockzhinerADCTriggerType::DoubleEdge);
  auto mode = static_cast<LockzhinerADCTriggerMode>(LockzhinerADCTriggerMode::Automatic);
  auto channel = static_cast<LockzhinerADCChannel>(LockzhinerADCChannel::ADCChannelAINNone);
  if (!base_device_->ConfigADCTrigger(type, mode, channel, level)) {
    qWarning(u8"DAQ控制器配置ADC触发失败");
  }

  // 长度 4920个点
  if (!base_device_->ConfigADCTriggerLength(4920)) {
    qWarning(u8"触发长度配置失败");
  }
  // 超时 100ms
  if (!base_device_->ConfigTriggerTimeout(100)) {
    qWarning(u8"超时时间配置失败");
  }

  // AC/DC 设置为DC
  uint8_t enable = 0x0F;
  if (!base_device_->ConfigACDC(enable)) {
    qWarning("配置AC/DC失败");
    return;
  }

  // 电压量程 1V
  if(!base_device_->ConfigADCVoltage(LockzhinerADCVoltage::ADCVoltage_1_V)){
    qWarning("配置电压量程失败");
  }

  qInfo(u8"下发配置成功");
}

void MainWindow::ClickSoftwareTrigger() {
  if (!base_device_->ConfigADCTriggerSource
    (static_cast<uint8_t>(libdaq::device::DAQADCTriggerSource::TriggerSourceSoftware))) {
    qWarning(u8"软件触发失败");
    return;
  }
  qInfo(u8"软件触发成功");
}

void MainWindow::ClickStopADCCollection() {
  is_start_adc_collection_ = false;
  if (!base_device_->StopADCCollection()) {
    qWarning(u8"停止ADC采集失败");
    return;
  }
  qInfo(u8"停止ADC采集成功");

}

void MainWindow::InitWaveWidget() {
  QVector<Qt::GlobalColor> channel_color_ = { // 通道颜色
    Qt::red, Qt::green, Qt::cyan, Qt::blue
  };
  base_wave_widget_ = QSharedPointer<BaseWaveWidget>::create();
  base_wave_widget_->InitChannel(2, channel_color_); // 初始化通道数


  QVector<bool> state = {true, true, true, true};
  base_wave_widget_->InitChannelState(state); // 初始化各通道数据显示状态
  ui->stackedWidget->addWidget(base_wave_widget_.get());
  ui->stackedWidget->setCurrentWidget(base_wave_widget_.get());
}

void MainWindow::ReceiveADCData(int channel) {
  auto channel_size = base_device_->GetADCLegalChannelSize();
  ADCDataState.resize(channel_size);
  ADCDataState[channel] = true;

  // 等待所有通道数据接收完成再显示
  for (int var = 0; var < ADCDataState.size(); ++var) {
    if (!ADCDataState[var]) {
      return;
    }
  }
  for (int var = 0; var < ADCDataState.size(); ++var) {
    ADCDataState[var] = false;
  }

  ContinuousCollectionUpdatePlotData();
}

void MainWindow::ContinuousCollectionUpdatePlotData() {
  if (!is_start_adc_collection_) {
    return;
  }
  base_wave_widget_->Clear();

  // 添加图表数据
  qInfo(u8"更新图表数据");
  for (int channel = 0; channel < ADC_Data_Buffer.size(); ++channel) {
    const auto &data = ADC_Data_Buffer[channel];
    if (data->empty()) {
      continue;
    }

    for (int index = 0; index < data->size(); ++index) {
      base_wave_widget_->AddData(channel, data->at(index));
    }
  }

  // 不开启滚动 直接设置为数据长度的范围
  base_wave_widget_->xAxis->setRange(0, 4920);
  base_wave_widget_->replot(QCustomPlot::rpQueuedReplot);

  AutomaticCollection();
}

void MainWindow::AutomaticCollection() {
  // 如果已经被停止，则不要再继续采集
  if (!is_start_adc_collection_) {
    return;
  }

  if (!base_device_->StopADCCollection()) {
    qWarning(u8"启动ADC采集失败");
    return;
  }

  if (!base_device_->StartADCCollection()) {
    qWarning(u8"启动ADC采集失败");
    return;
  }


  // 读取数据
  auto channel_number = base_device_->GetADCLegalChannelSize();

  // 确认上一次采集完成后再开始采集
  while (read_data_thread_pool_.activeThreadCount()) {
    QEventLoop loop;
    QTimer::singleShot(20, &loop, SLOT(quit()));
    loop.exec();
    QApplication::processEvents();
  }

  for (int channel_index = 0; channel_index < channel_number; ++channel_index) {
    // 获取需要读取数据的长度并初始化读取缓冲区
    ADC_Data_Buffer[channel_index] = std::make_shared<std::vector<float>>();
    auto buffer_size = ((4920 / 492) + 10) * 492;
    ADC_Data_Buffer[channel_index]->resize(buffer_size);
    // ADC_Data_Buffer[channel_index]->resize(2 * trigger_data_length);
    auto read_thread = new ContinuousReadADCThread(base_device_, channel_index, 4920,
                                                   ADC_Data_Buffer[channel_index]);
    connect(read_thread, &ContinuousReadADCThread::complete, this, &MainWindow::ReceiveADCData);
    read_thread->setAutoDelete(true);
    read_data_thread_pool_.start(read_thread);
  }
}

void MainWindow::ClickedConfigCalibration() {
  std::vector<uint8_t> data(12, 0);

  if (!base_device_->ConfigCalibration(data)) {
    QMessageBox::information(NULL, u8"错误", u8"启动校准失败", QMessageBox::Yes, QMessageBox::Yes);
    return;
  }

  int16_t channel_1 = 0;
  int16_t channel_2 = 0;
  int16_t channel_3 = 0;
  int16_t channel_4 = 0;

  auto channels = new uint8_t[12];
  auto move_pointer = reinterpret_cast<uint16_t *>(channels);
  move_pointer += 2;

  *move_pointer = channel_4;
  move_pointer++;

  *move_pointer = channel_3;
  move_pointer++;

  *move_pointer = channel_2;
  move_pointer++;

  *move_pointer = channel_1;
  move_pointer++;


  std::vector<uint8_t> vec(channels, channels + 12);
  // 下发偏移校正
  if (!base_device_->ConfigOffsetCalibrationX1(vec)) {
    qInfo("OffsetCalibrationX1 is error");
    return;
  }
  if (!base_device_->ConfigOffsetCalibrationX10(vec)) {
    qInfo("OffsetCalibrationX10 is error");
    return;
  }
  // 下发增益校正
  channel_1 = 32767;
  channel_2 = 32767;
  channel_3 = 32767;
  channel_4 = 32767;
  move_pointer = reinterpret_cast<uint16_t *>(channels);
  move_pointer += 2;

  *move_pointer = channel_4;
  move_pointer++;

  *move_pointer = channel_3;
  move_pointer++;

  *move_pointer = channel_2;
  move_pointer++;

  *move_pointer = channel_1;
  move_pointer++;

  std::vector<uint8_t> vec1(channels, channels + 12);
  if (channels) {
    delete[] channels;
    channels = nullptr;
  }
  if (!base_device_->ConfigGainCalibrationX1(vec1)) {
    qInfo("GainCalibrationX1 is error");
    return;
  }
  if (!base_device_->ConfigGainCalibrationX10(vec1)) {
    qInfo("GainCalibrationX1 is error");
    return;
  }


}
